home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / audio / midi / putmidi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  16.2 KB  |  505 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /* putmidi.c link with -lmidi -lm -lC */
  19.  
  20. #include <midi.h>
  21. #include <miditime.h>
  22. #include <midiio.h>
  23. #include <signal.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <math.h>
  27. /* for signal handler */
  28.  
  29. #define MAXEVENTS 1
  30.  
  31. int verbose = 0;
  32. int caught_sigint =  0;    /* completion flag */
  33. FILE *infile = stdin;
  34. MItime timeofday;               /* time of day of first event */
  35.  
  36. static char *types[] = {"MIMESSAGE","MISYSEX","MIREALTIME","MISYSCOM",""};
  37. static char *messages[] = {
  38.             "Off",
  39.             "On",
  40.             "PolyKeyPressure - ",
  41.             "Damper Pedal at ",
  42.             "All Notes Off at ",
  43.             "Omni Mode Off. next byte:",
  44.             "Omni Mode On. next byte:",
  45.             "Mono Mode On. next byte:",
  46.             "Poly Mode On. next byte:",
  47.             "Modulation Wheel at ",
  48.             "Program Change to #",
  49.             "Channel Pressue - ",
  50.             "Pitch Bender at ",
  51.             ""};
  52.  
  53. static int status[] = {
  54.             MIDI_NoteOff,
  55.             MIDI_NoteOn,
  56.             MIDI_PolyKeyPressure,
  57.             MIDI_ControlChange,
  58.             MIDI_ChannelModeSelect,    
  59.             MIDI_ChannelModeSelect,    
  60.             MIDI_ChannelModeSelect,    
  61.             MIDI_ChannelModeSelect,    
  62.             MIDI_ChannelModeSelect,    
  63.             MIDI_ControlChange,    
  64.             MIDI_ProgramChange,
  65.             MIDI_ChannelPressure,
  66.             MIDI_PitchBendChange,
  67.             0x0};
  68.  
  69. static int byte1[] = {
  70.             0x0,
  71.             0x0,
  72.             0x0,
  73.             MC_DamperPedal,
  74.             MC_AllNotesOff,
  75.             MC_OmniModeOff,
  76.             MC_OmniModeOn,
  77.             MC_MonoModeOn,
  78.             MC_PolyModeOn,
  79.             MC_ModulationWheel,
  80.             0x0,
  81.             0x0,
  82.             0x0,
  83.             0x0};
  84.             
  85.  
  86. void catch_sigint()
  87. {
  88.    caught_sigint=1;
  89. }
  90.  
  91. void printMImessage(MImessage mimsg) 
  92. /* Keep in mind this is done with what I could make out from the
  93. MIDI specification from the klunker Roland Juno-106 */
  94. {
  95.         printf("  device = %d, channel = %d, length = %d.\n",
  96.                 MIdevice(mimsg), MIchannel(mimsg), MIlength(mimsg));
  97.         printf("  status = ");
  98.         switch(MIstatus(mimsg) & MIDI_StatusMask)
  99.         {
  100. /*              case MIDI_ChannelVoice:  <-- these are the same */
  101.                 case MIDI_NoteOff:              /* 0x80 - 1000 0000 */ 
  102.                 {
  103.                         printf("Note %x Off - velocity %x\n",
  104.                                 MIbyte1(mimsg), MIbyte2(mimsg));
  105.                         break;
  106.                 }
  107.                 case MIDI_NoteOn:               /* 0x90 - 1001 0000 */
  108.                 {
  109.                         if(MIbyte2(mimsg) == 0)  /* this is equivalent */
  110.                                                  /* to a MIDI_NoteOff  */
  111.                         {
  112.                                 printf("Note %x Off - velocity 00\n",
  113.                                         MIbyte1(mimsg));
  114.                         }
  115.                         else
  116.                         {
  117.                                 printf("Note %x On - velocity %x\n",
  118.                                         MIbyte1(mimsg), MIbyte2(mimsg));
  119.                         }
  120.                         break;
  121.                 }
  122.                 case MIDI_PolyKeyPressure:      /* 0xa0 - 1010 0000 */
  123.                 {
  124.                         printf("PolyKeyPressure - %x\n",MIbyte2(mimsg));
  125.                         break;
  126.                 }
  127. /*               case MIDI_ControlChange:  <-- these are the same */
  128.                 case MIDI_ChannelModeSelect:    /* 0xb0 - 1011 0000 */
  129.                 {
  130.                         switch(MIbyte1(mimsg))
  131.                         {
  132.                                 case MC_DamperPedal: /* 0x40 - 0100 0000 */
  133.                                 {
  134.                                         printf("Damper Pedal at %x\n",
  135.                                                 MIbyte2(mimsg));
  136.                                 }
  137.                                 case MC_AllNotesOff: /* 0x7b - 0111 1011 */
  138.                                 {
  139.                                         printf("All Notes Off at %x\n",
  140.                                                 MIbyte2(mimsg));
  141.                                 }
  142.                                 case MC_OmniModeOff: /* 0x7c - 0111 1100 */
  143.                                 {
  144.                                         printf("Omni Mode Off. next byte:%x\n",
  145.                                                 MIbyte2(mimsg));
  146.                                 }
  147.                                 case MC_OmniModeOn:  /* 0x7d - 0111 1101 */
  148.                                 {
  149.                                         printf("Omni Mode On. next byte:%x\n",
  150.                                                 MIbyte2(mimsg));
  151.                                 }
  152.                                 case MC_MonoModeOn:  /* 0x7e - 0111 1110 */
  153.                                 {
  154.                                         printf("Mono Mode On. next byte:%x\n",
  155.                                                 MIbyte2(mimsg));
  156.                                 }
  157.                                 case MC_PolyModeOn:  /* 0x7f - 0111 1111 */
  158.                                 {
  159.                                         printf("Poly Mode On. next byte:%x\n",
  160.                                                 MIbyte2(mimsg));
  161.                                 }
  162.                                 case MC_ModulationWheel:/* 0x01 - 0000 0001 */
  163.                                 {
  164.                                         printf("Modulation Wheel at %x\n",
  165.                                                 MIbyte2(mimsg));
  166.                                 }
  167.                         }
  168.                         break;
  169.                 }
  170.                 case MIDI_ProgramChange:        /* 0xc0 - 1100 0000 */
  171.                 {
  172.                         printf("Program Change to #%x.\n",
  173.                                 MIbyte1(mimsg));
  174.                         break;
  175.                 }
  176.                 case MIDI_ChannelPressure:      /* 0xd0 - 1101 0000 */
  177.                 {
  178.                         printf("Channel Pressue - %x.\n",MIbyte1(mimsg));
  179.                         break;
  180.                 }
  181.                 case MIDI_PitchBendChange:      /* 0xe0 - 1110 0000 */
  182.                 {
  183.                         printf("Pitch Bender at %x.\n",
  184.                                 128 * MIbyte2(mimsg) + MIbyte1(mimsg));
  185.                         break;
  186.                 }
  187.         }
  188. }
  189.  
  190.  
  191. void printevents(MIevent *mievent, int num_events)
  192. {
  193. /* 
  194. Remember: within the MIevent structure is the timestamp and the message
  195. buffer. within the message buffer lies the MImessage structure and the buffer for system exclusive dats. 
  196. */
  197.  
  198. MItime          mitime;
  199. MImessage       mimsg;
  200. unsigned char   *misysexbuf;
  201. int i,j;
  202. static long eventnum = 0;
  203.  
  204.         if(!eventnum)   /* first event get time of day */
  205.         {
  206.                 printf("  STARTING time %d:%d:%f.\n",
  207.                         MItimegethours(&timeofday), 
  208.                         MItimegetminutes(&timeofday),
  209.                         (float)MItimegetsecs(&timeofday) + 
  210.                           ((float)MItimegetmicros(&timeofday) / 1000000.0));
  211.                 eventnum++;
  212.         }
  213.  
  214.         for (i=0; i < num_events; i++)
  215.         {
  216.                 printf("EVENT #%d - ",eventnum++);
  217. /*
  218.                 mitime = MItimesubtract(&mievent[i].dt,&timeofday);
  219. */
  220.                 MItimecopy(&mitime,&mievent[i].dt);
  221.                 mimsg  = mievent[i].mm.msgbuf; 
  222.                 misysexbuf  = mievent[i].mm.sysexbuf;
  223.                 switch(mievent[i].t)
  224.                 {
  225.                         case MIMESSAGE:
  226.                         {
  227.                                 printf("MIMESSAGE ( = %x)\n",mimsg);
  228.                                 printMImessage(mimsg);
  229.                                 break;
  230.                         }
  231.                         case MISYSEX:
  232.                         {
  233.                                 printf("MISYSEX\n");
  234.  
  235.                                 printf("%d bytes: ",mievent[i].count);
  236.                                 for(j=0; (j<mievent[i].count-1)&&(j<8); j++)
  237.                                         printf("%x, ",misysexbuf[j]);
  238.                                 printf("%x %s\n",misysexbuf[j],
  239.                                         ( (mievent[i].count > 8) ? "..." : ""));
  240.                                 break;
  241.                         }
  242.                         case MIREALTIME:
  243.                         {
  244.                                 printf("MIREALTIME\n");
  245.                                 break;
  246.                         }
  247.                         case MISYSCOM:
  248.                         {
  249.                                 printf("MISYSCOM\n");
  250.                                 break;
  251.                         }
  252.                         default:
  253.                         {
  254.                                 printf("unknown\n");
  255.                                 break;
  256.                         }
  257.                 }
  258.                 
  259.                 printf("  at time %lf.\n", MItimedouble(&mitime)/1000000.0); 
  260.         }
  261. }
  262.  
  263.  
  264.  
  265. int getevents(MIevent *mievent, int num_events)
  266. {
  267. char inline[80];
  268. char *shaker;
  269. int i,num,val;
  270. int channel,device;
  271. double secs;
  272. MItime mitime;
  273. MItime mitime2;
  274. static int firsttime = 1;
  275.  
  276.   if(firsttime)
  277.   {
  278.     firsttime = !firsttime;
  279.         fgets(inline,80,infile);
  280.         timeofday = MItimecurrentsystemtime(&timeofday);
  281.   }
  282.  
  283.   for(num=0;num<num_events;num++)
  284.   {
  285.     shaker = NULL;
  286.     while((!feof(infile)) && !shaker)
  287.     {
  288.         fgets(inline,80,infile);
  289.         shaker = strstr(inline,"EVENT");
  290.     }
  291.  
  292.     if (feof(infile)) return(-1-num);
  293.  
  294.     for(i=0; (types[i][0]) && !strstr(shaker,types[i]); i++); 
  295.     if(!types[i][0])
  296.     {
  297.         printf("unknown message type %s\n",shaker);
  298.         num--;
  299.     }
  300.     else
  301.     {
  302.         mievent[num].t = i;
  303.  
  304.         if (feof(infile)) return(-1-num);
  305.         fgets(inline,80,infile);
  306.  
  307.         if (!(shaker = strstr(inline,"channel = ")))
  308.         {
  309.             printf("no channel found.\n");
  310.             num--;
  311.         }
  312.         else
  313.         {
  314.             sscanf(shaker+strlen("channel = "),"%d",&channel);
  315.         MImakemessage(&mievent[num].mm.msgbuf,0x80,0x0,0x0,0x0);
  316.             MIsetchannel(&mievent[num].mm.msgbuf, channel);
  317. /* error in define for MIsetchannel ... was
  318. #define MIsetchannel(m, c) (__mp(m) &= 0xfff0ffff, __mp(m) |= ((c & 0xf) << 16),MIsetdevice(__mp(m) >> 4))
  319.  */
  320.  
  321.         shaker = strstr(inline,"device = ");
  322.             sscanf(shaker+strlen("device = "),"%d",&device);
  323.  
  324.             if (feof(infile)) return(-1-num);
  325.             fgets(inline,80,infile);
  326.  
  327.             if (!(shaker = strstr(inline,"status = ")))
  328.             {
  329.                 printf("no status found.\n");
  330.                 num--;
  331.             }
  332.             else
  333.             {
  334.                 for(i=0; (messages[i][0]) && 
  335.                     !strstr(shaker,messages[i]); i++); 
  336.                 if(!messages[i][0])
  337.                 {
  338.                     printf("unknown status type %s\n",shaker);
  339.                     num--;
  340.                 }
  341.                 else
  342.                 {
  343.                     MIsetstatus(&mievent[num].mm.msgbuf, status[i] >> 4);
  344.             if(status[i] != 
  345.             (MIstatus(mievent[num].mm.msgbuf) & MIDI_StatusMask))
  346.             {
  347.                       printf("oops! Status = %x\n",
  348.                     MIstatus(mievent[num].mm.msgbuf));
  349.             }
  350.  
  351.                     MIsetbyte1(&mievent[num].mm.msgbuf, byte1[i]);
  352.                     if((status[i] == MIDI_NoteOn) ||
  353.                        (status[i] == MIDI_NoteOff))
  354.                     {
  355.                         shaker = strstr(inline,"Note ");
  356.                         sscanf(shaker+strlen("Note "),"%x", &val);
  357.                         MIsetbyte1( &mievent[num].mm.msgbuf, val);
  358.  
  359.                         shaker = strstr(inline,"velocity ");
  360.                         sscanf(shaker+strlen("velocity "), "%x",&val);
  361.                         MIsetbyte2( &mievent[num].mm.msgbuf, val);
  362.                     }
  363.                     else
  364.                     {
  365.                         sscanf(shaker+strlen(messages[i]), "%x",&val);
  366.                         if (status[i] == MIDI_PitchBendChange)
  367.                         {
  368.                             MIsetbyte1( &mievent[num].mm.msgbuf, val%128);
  369.                             MIsetbyte2( &mievent[num].mm.msgbuf, val/128);
  370.                         }
  371.                         else if((status[i]==MIDI_ChannelPressure)||
  372.                             (status[i]==MIDI_ProgramChange)||
  373.                             (status[i]==MIDI_PolyKeyPressure))
  374.                         {
  375.                             MIsetbyte1( &mievent[num].mm.msgbuf, val);
  376.                         }
  377.                         else
  378.                         {
  379.                             MIsetbyte2( &mievent[num].mm.msgbuf, val);
  380.                         }
  381.                     }
  382.                     
  383.                     if (feof(infile)) return(-1-num);
  384.                     fgets(inline,80,infile);
  385.  
  386.                     if (!(shaker = strstr(inline,"  at time ")))
  387.                     {
  388.                         printf("no time found.\n");
  389.                         num--;
  390.                     }
  391.                     else
  392.                     {
  393.                         sscanf(shaker+strlen("  at time "), "%lf",
  394.                             &secs);
  395.                         
  396.             if(verbose)
  397.             printf("read time %lf (%lf %lf)\n",secs,
  398.                 floor(secs),
  399.                 fmod(secs*1000000.0,1000000.0));
  400.                         mitime = MItimecreatesecs((long)floor(secs),
  401.                 (long)fmod(secs*1000000.0,1000000.0));
  402.                         MItimecopy(&mievent[num].dt,&mitime);
  403.                     }
  404.                 }
  405.             }
  406.         }
  407.     }
  408.   }
  409.   return num;
  410. }
  411.  
  412.  
  413. main(int argc, char **argv)
  414. {
  415. MIconfig        *miconfig = MInewconfig();
  416. MIevent         mievent[MAXEVENTS];
  417. MIport          *miPort = MInewport();
  418. extern char *optarg;
  419. char *infilename;
  420. int num;
  421. int c;
  422. int errflag = 0;
  423. static unsigned int pbuf[] = {
  424.     MI_STAMPING, MIRELSTAMP,
  425.     MI_BLOCKING, MINONBLOCKING,
  426.     MI_TIMEOUT, 0, 0,
  427.     MI_OUTPUTTIME, 2, 0 
  428.     };
  429. /* config stuff */
  430.          while ((c = getopt(argc, argv, "vf:")) != EOF)
  431.                switch (c) {
  432.                case 'v':
  433.                     verbose++;
  434.                     break;
  435.                case 'f':
  436.                     infilename = optarg;
  437.                     break;
  438.                case '?':
  439.                     errflag++;
  440.                }
  441.     if(errflag)
  442.     {
  443.         printf("usage: %s [-v] -f <infile>\n",argv[0]);
  444.         exit(1);
  445.     }
  446.  
  447.     sigset(SIGINT,catch_sigint);
  448.     MIsetparams(miconfig,pbuf, 10);
  449.  
  450.         if (MIopen(miPort,"w", miconfig) == -1) /* open midi port */
  451.         {
  452.         if(verbose)
  453.                     printf("MIopen: Couldn't open midi port for writing\n");
  454.                 exit(1);
  455.         }
  456.     if(verbose)
  457.     {
  458.             printf("MIopen succeded.\n");
  459.  
  460.         printf("MIgetfd: file descriptor is %x\n.", MIgetfd(miPort));
  461.     }
  462.  
  463.     MIsetstart(miPort,NULL);
  464.         timeofday = MItimecurrentsystemtime(&timeofday);
  465.  
  466.     infile = fopen(infilename,"r");
  467.         while(!caught_sigint)
  468.         {
  469.                 num = getevents(mievent,MAXEVENTS);
  470.                 if (num == 0)
  471.         {
  472.             if(verbose)
  473.                 printf("error reading event\n");
  474.         }  
  475.         else if (num < 0)
  476.         {
  477.             if(verbose)
  478.             {
  479.                 printf("end of file\n");
  480.                 printevents(mievent,-num-1);
  481.             }
  482.                         num = MIsend(miPort,mievent,-num-1);
  483.             caught_sigint = 1;
  484.         }
  485.         else
  486.         {
  487.             if(verbose)
  488.                 printevents(mievent,MAXEVENTS);
  489.                     num = MIsend(miPort,mievent,MAXEVENTS);
  490.                     if(num == -1)
  491.                     {
  492.             if(verbose)
  493.                                 printf("Error in MIsend.\n");
  494.                         exit(1);
  495.                     }
  496.         }
  497.         }
  498.  
  499.     sleep(3);
  500.         MIclose(miPort);        /* close midi port */
  501.  
  502.         free(miPort);
  503.         free(miconfig);
  504. }
  505.